#include "dmr_gpio.h"
#include "dmr_i2c.h"
#include "dmr_delay.h"
#include "stdio.h"

#define _I2C_SCL_H(handle)		dmr_gpioWritePinLevel(handle->sclGpiox,handle->sclPin,true)
#define _I2C_SCL_L(handle)		dmr_gpioWritePinLevel(handle->sclGpiox,handle->sclPin,false)

#define _I2C_SDA_H(handle)		dmr_gpioWritePinLevel(handle->sdaGpiox,handle->sdaPin,true)
#define _I2C_SDA_L(handle)		dmr_gpioWritePinLevel(handle->sdaGpiox,handle->sdaPin,false)
#define _I2C_READ_SDA(handle)	dmr_gpioReadPinLevel(handle->sdaGpiox,handle->sdaPin)

#define _I2C_DELAY(us)		dmr_delayUs(us)



static void _i2cStart(dmr_i2cHandle *handle);
static void _i2cStop(dmr_i2cHandle *handle);
static uint8_t _i2cWaitAck(dmr_i2cHandle *handle);
static void _i2cWriteAck(dmr_i2cHandle *handle,uint8_t ack);
static void _i2cWriteByte(dmr_i2cHandle *handle,uint8_t dat);
static  uint8_t _i2cReadByte(dmr_i2cHandle *handle,uint8_t ack);


void dmr_i2cInit(dmr_i2cHandle *handle)
{
	dmr_gpioHandle _gpioConfig_t = {0};
		
	_gpioConfig_t.speed		= GPIO_SLEW_RATE_FAST;
	_gpioConfig_t.pull 		= GPIO_PULL_UP;
	_gpioConfig_t.mode		= GPIO_MODE_OUT_OD;
	_gpioConfig_t.current	= GPIO_DS_4MA;
	_gpioConfig_t.pin		= handle->sdaPin;
	_gpioConfig_t.gpiox 	= handle->sdaGpiox;
	dmr_gpioInit(&_gpioConfig_t);
	
	_gpioConfig_t.pin		= handle->sclPin;
	_gpioConfig_t.gpiox 	= handle->sclGpiox;
	dmr_gpioInit(&_gpioConfig_t);
	
	dmr_gpioWritePinLevel(handle->sdaGpiox,handle->sdaPin,true);
	dmr_gpioWritePinLevel(handle->sclGpiox,handle->sclPin,true);
}


uint8_t dmr_i2cMasterSendByte(dmr_i2cHandle *handle ,uint8_t* tData, uint8_t tLen)
{
	uint8_t var;

	_i2cStart(handle);
	_i2cWriteByte(handle,handle->slaveAddr<<1);//发送设备地址
	_i2cWaitAck(handle);

	_i2cWriteByte(handle,tData[0]);
	_i2cWaitAck(handle);

	for (var = 0; var < tLen-1; ++var)
	{
		_i2cWriteByte(handle,*(++tData));
		_i2cWaitAck(handle);
	}
	
	_i2cStop(handle);
	
	return 0;
}

uint8_t dmr_i2cMasterRecvByte(dmr_i2cHandle *handle ,uint8_t registerAddr,uint8_t* rData, uint8_t rLen)
{
	uint8_t var;
	
	_i2cStart(handle);	
	_i2cWriteByte(handle,handle->slaveAddr<<1);//发送设备地址
	_i2cWaitAck(handle);	
	_i2cWriteByte(handle,registerAddr);	//发送要读的寄存器
	_i2cWaitAck(handle);	

	_i2cStart(handle);		
	_i2cWriteByte(handle,handle->slaveAddr<<1|0x1);	//发送设备地址+1 即读数据
	_i2cWaitAck(handle);	
	
	for (var = 0; var < rLen - 1 ; ++var)
	{
		rData[var] = _i2cReadByte(handle,0);	//连续读 响应ACK
	}

	rData[var] = _i2cReadByte(handle,1);	//读最后一个 不响应ACK

	_i2cStop(handle);

	return 0;
}


static void _i2cStart(dmr_i2cHandle *handle)
{
	
	_I2C_SCL_H(handle);
	_I2C_DELAY(2);
	
	_I2C_SDA_H(handle);
	_I2C_DELAY(2);
	_I2C_SDA_L(handle);
	_I2C_DELAY(2);
	
 	_I2C_SCL_L(handle);
	_I2C_DELAY(2);
}

static void _i2cStop(dmr_i2cHandle *handle)
{
	
	_I2C_SDA_L(handle);
	_I2C_DELAY(2);
	
	_I2C_SCL_H(handle);
	_I2C_DELAY(2);
	
	_I2C_SDA_H(handle);
	_I2C_DELAY(2);
}


static uint8_t _i2cWaitAck(dmr_i2cHandle *handle)
{
	uint8_t res=0;
	
	_I2C_SCL_L(handle);
	_I2C_DELAY(2);
	
	_I2C_SDA_H(handle);
	_I2C_DELAY(2);
	
	_I2C_SCL_H(handle);
	_I2C_DELAY(2);
	
	if(_I2C_READ_SDA(handle))
	{
		res = 1;
	}

	
	_I2C_SCL_L(handle);
	_I2C_DELAY(2);
	
	return res;
}

static void _i2cWriteAck(dmr_i2cHandle *handle,uint8_t ack)
{
	_I2C_SCL_L(handle);
	
	_I2C_DELAY(2);
	if(ack != 0)
	{
		_I2C_SDA_H(handle);
	}
	else
	{
		_I2C_SDA_L(handle);
	}
	_I2C_DELAY(2);
	
	_I2C_SCL_H(handle);
	_I2C_DELAY(2);
	_I2C_SCL_L(handle);
	_I2C_DELAY(2);
}


static void _i2cWriteByte(dmr_i2cHandle *handle,uint8_t dat)
{
	uint8_t t;
	
	
    for(t = 0; t < 8; ++t)
    {
		_I2C_SCL_L(handle);
    	_I2C_DELAY(3);
		
		if(dat&0x80)
		{
			_I2C_SDA_H(handle);
		}
		else
		{
			_I2C_SDA_L(handle);
		}
		
		dat<<=1;
		_I2C_SCL_H(handle);
		_I2C_DELAY(3);
    }
}

//读1个字节，ack=0时，发送ACK，ack=1，发送nACK
static  uint8_t _i2cReadByte(dmr_i2cHandle *handle,uint8_t ack)
{
	uint8_t i,Receive_Value=0;
	
	
	_I2C_SCL_L(handle);
	_I2C_DELAY(2);
	
	_I2C_SDA_H(handle);
	
    for(i = 0; i < 8; ++i)
	{
		_I2C_SCL_H(handle);
		_I2C_DELAY(3);
		Receive_Value<<=1;
		if(_I2C_READ_SDA(handle))
		{
			Receive_Value|=0x01;
		}
		_I2C_SCL_L(handle);
		_I2C_DELAY(3);
    }
    _i2cWriteAck(handle,ack);

    _I2C_SCL_L(handle);
    return Receive_Value;
}



